﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;

using System.Linq;
using System.Linq.Expressions;

using ProjectBase.Core;

using $prjsn$.Common;
using $prjsn$.Common.Validation;

namespace $safeprojectname$
{
    /// <summary>Assures that passed array is not null nor empty</summary>
    public class NotEmptyEnumerableRule<TItem, TValue> : RuleBase, IValidationRule<TItem>
        where TItem : class
    {
        #region members

        private readonly Func<TItem, IEnumerable<TValue>> _compiledExpression;

        #endregion members

        #region Constructor

        public NotEmptyEnumerableRule(Expression<Func<TItem, IEnumerable<TValue>>> expression)
        {
            var body = expression.Body as MemberExpression;
            if (body.IsNull())
            {
                throw new NotSupportedException(
                    "Provided 'Expression<Func<TITem, IEnumerable<TValue>>>' must be of a 'ExpressionType.MemberAccess' (EnumerableRule). ");
            }

            PropertyName = body.Member.Name;
            _compiledExpression = expression.Compile();
        }

        public NotEmptyEnumerableRule(Func<TItem, IEnumerable<TValue>> expression, string propertyName)
        {
            PropertyName = propertyName;
            _compiledExpression = expression;
        }

        #endregion Constructor

        #region Validate

        public virtual ValidationResult Validate(TItem item, out ValidationMessage message)
        {
            message = null;

            // item cannot be null
            if (item.IsNull())
            {
                message = new ValidationMessage(Str.Messages.NullInsteadOfEntityProvided1)
                {
                    EntityName,
                };
                return ValidationResult.Error;
            }

            var result = CompiledExpression.Invoke(item);

            // IEnumerable is null or empty
            if (result.IsEmpty())
            {
                message = new ValidationMessage(Str.Messages.EmptyCollection1)
                {
                    PropertyName.GetLocalized(EntityName),
                };
                return ValidationResult.Error;
            }

            return ValidationResult.IsValid;
        }

        #endregion Validate

        #region Client

        public override IMDValidationRule GetMetaDataRule()
        {
            return new MDMandatoryRule
            {
                Type = "NotEmptyEnumerableRule",
                IsRequired = true,
            };
        }

        #endregion Client

        #region properties

        protected virtual Func<TItem, IEnumerable<TValue>> CompiledExpression { get { return _compiledExpression; } }
        protected virtual string EntityName { get { return typeof(TItem).Name; } }

        #endregion properties
    }
}